#include "Renderer.h"
#include "MathDX.h"
using namespace pg1;

D3DPRIMITIVETYPE primitivesMapping[PrimitiveCount] =
{
	D3DPT_TRIANGLELIST, 
	D3DPT_TRIANGLESTRIP,
	D3DPT_POINTLIST,
	D3DPT_LINELIST,     
	D3DPT_LINESTRIP,
	D3DPT_TRIANGLEFAN
};

D3DTRANSFORMSTATETYPE g_eMatrixTypeMapping [MatrixTypeCount] =
{
	D3DTS_VIEW,
	D3DTS_PROJECTION,
	D3DTS_WORLD
};



pg1::Renderer::Renderer():
	r_Device(NULL),
	r_D3D(NULL),
	r_colorVB(NULL)
{
	
}

pg1::Renderer::~Renderer()
{
	//Debug Assertion
	if(r_colorVB){
		delete r_colorVB;
		r_colorVB = NULL;
	}
	if(r_D3D){
		r_D3D->Release();
		r_D3D = NULL;
	}

	if(r_Device){
		r_Device->Release();
		r_Device = NULL;
	}
}

bool pg1::Renderer::init(HWND hWnd)
{
	r_D3D = Direct3DCreate9(D3D_SDK_VERSION);
	                                                    
	if (!r_D3D)
		return false;

	D3DDISPLAYMODE displayMode;
	r_D3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &displayMode);

	D3DPRESENT_PARAMETERS parametersD3D;
	ZeroMemory( &parametersD3D, sizeof(parametersD3D));
	parametersD3D.Windowed = TRUE;
	parametersD3D.SwapEffect = D3DSWAPEFFECT_DISCARD;
	parametersD3D.hDeviceWindow = hWnd;
	

	

	if(r_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, 
		&parametersD3D, &r_Device) ==D3D_OK)
	{
		r_Device->SetRenderState(D3DRS_LIGHTING,false);
		//r_Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
		r_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
		r_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
		r_Device->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
		r_Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
		r_Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
		//Matrix World and View
		D3DVIEWPORT9 matViewPort;  
		r_Device->GetViewport(&matViewPort);
		float fViewportWidth= static_cast<float>(matViewPort.Width);
		float fViewportHeight= static_cast<float>(matViewPort.Height);

		D3DXMATRIX matrixProjectionTransfom;
		D3DXMatrixOrthoLH(&matrixProjectionTransfom,			 
								   fViewportWidth,    
								   fViewportHeight, 
								   -1.0f,    
								   1.0f);   
		r_Device->SetTransform(D3DTS_PROJECTION, &matrixProjectionTransfom);
		//End Matrix World and View
		r_colorVB = new VertexBuffer(r_Device, sizeof(ColorVertex), ColorVertexType);
			m_pkTextureCoordVB = new pg1::VertexBuffer(r_Device,
												sizeof(pg1::TextureCoordVertex),
											    pg1::TextureCoordVertexType);

			return true;
	}

	return false;
}
void pg1::Renderer::setMatrix(MatrixType eMatrixType,const Matrix& matrix)
	{
		r_Device->SetTransform(g_eMatrixTypeMapping[eMatrixType],matrix);
	}
void pg1::Renderer::Draw(ColorVertex* vertex, Primitive primitive,size_t vertexCount){
	
	r_colorVB->bind();
	r_colorVB->draw(vertex, primitivesMapping[primitive], vertexCount);
	
}

void pg1::Renderer::Draw(TextureCoordVertex* apkVertices,pg1::Primitive primitive,size_t vertexCount)
	{
		m_pkTextureCoordVB->bind();
		m_pkTextureCoordVB->draw(apkVertices,
						  primitivesMapping[primitive],
						  vertexCount);
	}









void pg1::Renderer::beginFrame(){
	
	r_Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
	//r_Device->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xff606060, 1.0f, 0);
	r_Device->BeginScene();

}

void pg1::Renderer::endFrame(){

	r_colorVB->flush();

	r_Device->EndScene();
	r_Device->Present(NULL, NULL, NULL, NULL);

}
void pg1::Renderer::setCurrentTexture(const Texture& rkTexture){
		r_Device->SetTexture(0, rkTexture);//el 0 es para especificar si es normalmap, difuse, specular, etc;
	}

	const Texture pg1::Renderer::loadTexture (const std::string& rkFilename,int iColorKey){
		IDirect3DTexture9* pkTexture = NULL;
		HRESULT hr= D3DXCreateTextureFromFileEx(
												r_Device,
												rkFilename.c_str(),
												0,0,0,0,
												D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
												D3DX_FILTER_NONE, D3DX_FILTER_NONE,
												iColorKey,
												NULL,
												NULL,
												&pkTexture
		);
		
		if(hr!=D3D_OK){
			return NoTexture;
		}
		else{
			m_akTextures.push_back(pkTexture);
			return pkTexture;
		}
	
	}